﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Net;
using System.Net.Sockets;

namespace SimaticModbusTcpLib
{
    //public static TcpHandle MacMiniTCP = new TcpHandle("169.254.1.10", 1111);//TCPHandle 对象  IP+端口号
    public class TcpHandle
    {
        private object obj;
        private IPEndPoint m_Ipe;
        public Socket m_Client;
        private AutoResetEvent m_ConnectEvent;
        private AutoResetEvent m_SendEvent;
        private AutoResetEvent m_ReceiveEvent;

        public byte[] m_BufferVlaue;

        public bool isrec = false;
        public byte[] BufferVlaue
        {
            get { return m_BufferVlaue; }
            set { m_BufferVlaue = value; }
        }

        public TcpHandle(string host, int port)
        {
            this.m_Ipe = new IPEndPoint(IPAddress.Parse(host), port);
            m_ConnectEvent = new AutoResetEvent(false);
            m_SendEvent = new AutoResetEvent(false);
            m_ReceiveEvent = new AutoResetEvent(false);
            m_BufferVlaue = new byte[8192];
            obj = new object();
        }


        public bool BeginConnect(int timeOut)
        {
            try
            {
                m_Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_Client.BeginConnect(m_Ipe, new AsyncCallback(ConnectCallBack), m_Client);
                if (m_ConnectEvent.WaitOne(timeOut))
                {
                    return true;
                }
                else
                {
                    CloseSocket();
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }


        private void ConnectCallBack(IAsyncResult ar)
        {
            try
            {
                Socket socket = (Socket)ar.AsyncState;
                socket.EndConnect(ar);
                m_ConnectEvent.Set();
            }
            catch
            {
                CloseSocket();
            }
            finally
            {
                //m_ConnectEvent.Set();
            }

        }


        public bool BeginSend(byte[] value, int timeOut)
        {
            try
            {
                //BeginReceive(20);//发送前先将缓存区的数据接收出来，确保下次接收的是最新有用的数据
                isrec = false;//将标志位置False
                for (int i = 0; i < m_BufferVlaue.Length; i++)
                {
                    m_BufferVlaue[i] = 0;
                }
                m_Client.BeginSend(value, 0, value.Length, SocketFlags.None, new AsyncCallback(SendCallBack), m_Client);
                if (m_SendEvent.WaitOne(timeOut))
                {
                    return true;
                }
                else
                {
                    //CloseSocket();
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        public bool BeginSend1(byte[] value, int timeOut)
        {
            try
            {
                //BeginReceive(20);//发送前先将缓存区的数据接收出来，确保下次接收的是最新有用的数据
                //isrec = false;//将标志位置False
                //for (int i = 0; i < m_BufferVlaue.Length; i++)
                //{
                //    m_BufferVlaue[i] = 0;
                //}
                m_Client.BeginSend(value, 0, value.Length, SocketFlags.None, new AsyncCallback(SendCallBack), m_Client);
                if (m_SendEvent.WaitOne(timeOut))
                {
                    return true;
                }
                else
                {
                    //CloseSocket();
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }


        private void SendCallBack(IAsyncResult ar)
        {
            try
            {
                Socket socket = (Socket)ar.AsyncState;
                socket.EndSend(ar);
            }
            catch
            {
                //CloseSocket();
            }
            finally
            {
                m_SendEvent.Set();
            }
        }


        public bool BeginReceive(int timeout)
        {
            try
            {
                for (int i = 0; i < m_BufferVlaue.Length; i++)
                {
                    m_BufferVlaue[i] = 0;
                }
                m_Client.BeginReceive(m_BufferVlaue, 0, m_BufferVlaue.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), m_Client);
                if (m_ReceiveEvent.WaitOne(timeout))
                {
                    return true;
                }
                else
                {
                    //CloseSocket();
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }


        private void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                Socket socket = (Socket)ar.AsyncState;
                int count = socket.EndReceive(ar);

                //System.Text.Encoding.ASCII.GetString(m_BufferVlaue, 0, count);
            }
            catch
            {
                //CloseSocket();
            }
            finally
            {
                m_ReceiveEvent.Set();
            }
        }

        public bool SocketResponse(byte[] sendByte, int timeout)
        {
            lock (obj)
            {
                try
                {
                    BeginReceive(10);//发送接收前先将缓存区的数据接收出来，确保本次接收的是最新有用的数据
                    if (!BeginSend(sendByte, timeout))
                    {
                        return false;
                    }
                    else
                    {
                        if (!BeginReceive(timeout))
                        {
                            return false;
                        }
                        else
                        {
                            return true;
                        }
                    }
                }
                catch
                {
                    return false;
                }
            }
        }

        public void CloseSocket()
        {
            try
            {
                m_SendEvent.Reset();
                m_ReceiveEvent.Reset();
                m_ConnectEvent.Reset();
            }
            catch (SocketException ex)
            {
                throw ex;
            }
            finally
            {
                m_Client.Close();
            }
        }

        public void BeginReceive1()
        {
            m_Client.BeginReceive(m_BufferVlaue, 0, m_BufferVlaue.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack1), m_Client);
        }

        private void ReceiveCallBack1(IAsyncResult ar)
        {
            try
            {
                Socket socket = (Socket)ar.AsyncState;
                int count = socket.EndReceive(ar);
                isrec = true;
                //Thread.Sleep(3000);
                //for (int i = 0; i < m_BufferVlaue.Length; i++)
                //{
                //    m_BufferVlaue[i] = 0;
                //}
                BeginReceive1();

            }
            catch
            {
                //CloseSocket();
            }
            finally
            {
                //m_ReceiveEvent.Set();
            }
        }
    }
}
